'use client';

import type {
  ICreateReplyBody,
  IPostClientDetails,
  IPostComment,
  IPostCommentReply,
  IQueryParams,
} from '@/interfaces';
import type { TBody, TMetadata } from '@/types';
import useUser from '@/hooks/useUser';
import { type ChangeEvent, useEffect, useState } from 'react';
import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import { createReply, queryAllReplyByCommentId } from '@/services/api';
import sanitizeHtml from 'sanitize-html';
import Image from 'next/image';
import { getUserAvatar, toRelativeTime } from '@/lib/tool';
import Link from 'next/link';
import classNames from 'classnames';
import Reply from '@/app/[locale]/posts/[id]/reply';
import { useTranslations } from 'use-intl';

export default function Comment({
  commentItem,
  commentIndex,
  postData,
  metadata,
}: {
  commentItem: IPostComment;
  commentIndex: number;
  postData: IPostClientDetails;
  metadata: TMetadata;
}) {
  const env = metadata.env;
  const userQuery = useUser(metadata);
  const [replyContent, setReplyContent] = useState('');
  const { show } = useToast();
  const [queryParams, setQueryParams] = useState<IQueryParams>({});
  const [isClickLoadMore, setIsClickLoadMore] = useState(false);
  const [pages, setPages] = useState<IPostCommentReply[]>(commentItem.content);
  const t = useTranslations('PostIdPage');

  const replyQuery = useInfiniteQuery(
    ['/forum', '/replies', '/comments', commentItem.comment.id, queryParams],
    async (context) => {
      return (await queryAllReplyByCommentId({
        id: context.queryKey[3],
        query: {
          ...(context.queryKey[4] as IQueryParams),
          ...context.pageParam,
        },
      })) as IPostComment;
    },
    {
      enabled: isClickLoadMore,
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (firstPage.pageable.previous) {
          return {
            page: Math.max(firstPage.pageable.page - 1, 0),
            size: firstPage.pageable.size,
          };
        }
      },
      getNextPageParam: (lastPage) => {
        if (lastPage.pageable.next) {
          return {
            page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
            size: lastPage.pageable.size,
          };
        }
      },
      initialData: () => {
        return {
          pages: [commentItem],
          pageParams: [
            {
              page: Math.max(commentItem.pageable.page - 1, 0),
              size: commentItem.pageable.size,
            },
          ],
        };
      },
    },
  );

  const createReplyMutation = useMutation(
    async (variables: TBody<ICreateReplyBody>) => {
      await createReply(variables);
      await replyQuery.refetch({ throwOnError: true });
    },
  );

  useEffect(() => {
    if (replyQuery.data) {
      setPages(
        replyQuery.data.pages
          .flatMap((item) => item.content)
          .map((item) => {
            item.reply._createdOnText = toRelativeTime(item.reply.createdOn);
            return item;
          }),
      );
    }
  }, [replyQuery.data]);

  async function onClickPostReply() {
    if (!userQuery.data?.user) {
      show({
        title: t('notLoggedInPrompt'),
        content: <LoginReminderContent />,
      });
      return;
    }

    const _replyContent = replyContent.trim();
    if (!_replyContent) {
      show({
        type: 'DANGER',
        message: t('replyContentEmptyError'),
      });
      return;
    }

    const content = sanitizeHtml(_replyContent);
    if (!content) {
      show({
        type: 'DANGER',
        message: t('replyContentEmptyError'),
      });
      return;
    }

    try {
      const commentId = commentItem.comment.id;
      await createReplyMutation.mutateAsync({
        data: {
          commentId,
          content,
        },
      });

      setReplyContent('');
      show({
        type: 'SUCCESS',
        message: t('replyCompleted'),
      });
    } catch (e) {
      createReplyMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickLoadMore() {
    setIsClickLoadMore(true);

    try {
      await replyQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeReplyContent(e: ChangeEvent<HTMLTextAreaElement>) {
    setReplyContent(e.target.value);
  }

  return (
    <div className="row overflow-hidden">
      <div className="col-12 col-lg-2 d-none d-lg-block pe-0">
        <div
          className="card h-100 border-0 rounded-0 vstack gap-2"
          style={{
            borderBottomLeftRadius: '0.376rem !important',
          }}
        >
          <div
            className="align-self-center my-4"
            style={{ width: 128, height: 128 }}
          >
            <Image
              priority
              className="rounded-circle card-img-top"
              src={getUserAvatar(commentItem.user, metadata).mediumAvatarUrl}
              alt={commentItem.user.alias}
              title={commentItem.user.alias}
              width={128}
              height={128}
              placeholder="blur"
              blurDataURL={env.APP_BLUR_DATA_URL}
              style={{
                maxWidth: '100%',
                objectFit: 'cover',
              }}
            />
          </div>
          <div className="card-body align-self-center text-center">
            <h5 className="card-title">
              <Link
                href={`/users/${commentItem.user.id}`}
                className="text-decoration-none text-dark text-decoration-underline-hover"
              >
                {commentItem.user.alias}
              </Link>
            </h5>

            <p className="card-text my-3">
              {commentItem.user.roles
                .filter((item) => !item.hide)
                .map((item) => item.name)
                .join(' / ')}
            </p>
          </div>
          <div className="card-footer border-top-0 border-bottom border-secondary border-opacity-10">
            <small className="text-muted" title={t('contentUpdatedTime')}>
              {t('lastUpdated')}&nbsp;
              <time
                className={classNames(
                  commentItem.comment._createdOnText ? false : 'invisible',
                )}
                dateTime={commentItem.comment.createdOn}
              >
                {commentItem.comment._createdOnText}
              </time>
            </small>
          </div>
        </div>
      </div>
      <div className="col-auto border-1 px-0 border-secondary border-opacity-10 border-end"></div>
      <div className="col col-lg-9 flex-grow-1 ps-0">
        <div
          className="card border-0 border-secondary border-opacity-10 rounded-0 h-100 border-bottom"
          style={{
            borderBottomRightRadius: '0.376rem !important',
          }}
        >
          <div className="card-body">
            <div className={classNames('position-absolute top-0 end-0 mx-3')}>
              <small
                title={`${t('currentFloorNumber')} ${commentIndex + 2}`}
                className="text-muted user-select-none"
              >
                {commentIndex + 2}
              </small>
            </div>

            <div
              className="clearfix content-layer content-layer-pc mt-3 mb-7 text-break"
              dangerouslySetInnerHTML={{
                __html: commentItem.comment.content ?? '',
              }}
            ></div>

            {userQuery.data && userQuery.data.user && (
              <div className="my-7">
                <div className="text-muted">
                  <a
                    className="user-select-none text-muted text-decoration-none text-decoration-underline-hover"
                    data-bs-toggle="collapse"
                    href={`#yw-c-${commentItem.comment.id}`}
                    role="button"
                    aria-expanded="false"
                    aria-controls={`yw-c-${commentItem.comment.id}`}
                  >
                    回复
                  </a>
                </div>

                <div className="collapse" id={`yw-c-${commentItem.comment.id}`}>
                  <div>
                    <textarea
                      className="form-control my-3"
                      rows={4}
                      placeholder={t('enterReply')}
                      name="replyContent"
                      value={replyContent}
                      onChange={onChangeReplyContent}
                    ></textarea>
                    <button
                      disabled={createReplyMutation.isLoading || !replyContent}
                      onClick={onClickPostReply}
                      type="button"
                      className="btn btn-outline-primary my-3 w-100"
                    >
                      {createReplyMutation.isLoading ? (
                        <span
                          className="spinner-border spinner-border-sm me-2"
                          role="status"
                          aria-hidden="true"
                        ></span>
                      ) : (
                        <i className="bi bi-cursor me-2"></i>
                      )}
                      {t('postReply')}
                    </button>
                  </div>
                </div>
              </div>
            )}

            {pages.length > 0 && (
              <div className="vstack gap-4 my-5">
                {pages.map((item, index) => {
                  return (
                    <Reply
                      key={item.reply.id}
                      replyItem={item}
                      replyIndex={index}
                      commentItem={commentItem}
                      commentIndex={commentIndex}
                      postData={postData}
                      metadata={metadata}
                    />
                  );
                })}
              </div>
            )}

            {replyQuery.hasNextPage && (
              <div className="row">
                <div className="col rounded">
                  <button
                    onClick={onClickLoadMore}
                    disabled={
                      !replyQuery.hasNextPage || replyQuery.isFetchingNextPage
                    }
                    type="button"
                    className="btn btn-light w-100 text-secondary"
                  >
                    {replyQuery.isFetchingNextPage ? (
                      <>
                        <span
                          className="spinner-border spinner-border-sm me-2"
                          role="status"
                          aria-hidden="true"
                        ></span>
                        Loading...
                      </>
                    ) : (
                      <i className="bi bi-three-dots me-2"></i>
                    )}
                  </button>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
